package me.whf.framework;

import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Timer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import me.whf.dao.EmployeeDAO;
import me.whf.dao.factory.DAOFactory;
import me.whf.util.DailyTask;
import me.whf.util.MonthTask;
import me.whf.util.Utils;
import me.whf.util.Utils.EmployeeType;

public class WebAppListener implements ServletContextListener {
	
	private static String WEB_CONTENT;
	private final String ACCOUNT_FILE = "/data/account.txt";
	private final String VIPSTUFF_FILE = "/data/vipstuff.txt";
	private final String ENTERPRISE_FILE = "/data/enterprise.txt";
	private final String LOGGER_FILE = "/data/logger.txt";
	private final String APARTMENT_FILE = "/data/apartment.txt";
	private final String EMPLOYEE_FILE = "/data/employee.txt";
	
	private Timer dailyTimer;
	private Timer monthTimer;

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		if (Utils.storage == Utils.Storage.FILE) {
			writeFile(WEB_CONTENT + ACCOUNT_FILE, Utils.accounts);
			writeFile(WEB_CONTENT + VIPSTUFF_FILE, Utils.vipstuff);
			writeFile(WEB_CONTENT + ENTERPRISE_FILE, Utils.enterprises);
			writeFile(WEB_CONTENT + LOGGER_FILE, Utils.loggers);
			writeFile(WEB_CONTENT + APARTMENT_FILE, Utils.apartments);
			writeFile(WEB_CONTENT + EMPLOYEE_FILE, Utils.employees);
		}
		if (dailyTimer != null) {
			dailyTimer.cancel();
		}
		if (monthTimer != null) {
			monthTimer.cancel();
		}
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		BufferedReader reader = new BufferedReader(new InputStreamReader((this.getClass().getClassLoader().getResourceAsStream("config.txt"))));
		String storageType = "";
		try {
			storageType = reader.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		Utils.storage = Utils.Storage.valueOf(storageType);
		
		if (Utils.storage == Utils.Storage.FILE) {
			String path = this.getClass().getClassLoader().getResource("").toString();
			WEB_CONTENT = path.replaceFirst("WEB-INF/classes/", "");
			
			readFile(WEB_CONTENT + ACCOUNT_FILE, Utils.accounts);
			readFile(WEB_CONTENT + VIPSTUFF_FILE, Utils.vipstuff);
			readFile(WEB_CONTENT + ENTERPRISE_FILE, Utils.enterprises);
			readFile(WEB_CONTENT + LOGGER_FILE, Utils.loggers);
			readFile(WEB_CONTENT + APARTMENT_FILE, Utils.apartments);
			boolean isEmpty = readFile(WEB_CONTENT + EMPLOYEE_FILE, Utils.employees);
			
			if (isEmpty)
			{
				EmployeeDAO employeeDAO = DAOFactory.getDAOFactory().getEmployeeDAO();
				employeeDAO.register("admin", "admin", "admin", "admin", EmployeeType.ADMINISTRATOR);
			}
		}
		setupDailyTimer();
		setupMonthTimer();
	}
	
	private void setupDailyTimer() {
		dailyTimer = new Timer();
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 1);  
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.add(Calendar.DATE, 1);
		
		Date date = calendar.getTime();
		dailyTimer = new Timer();
		Long period = Long.valueOf(24 * 60 * 60 * 1000);
		dailyTimer.schedule(new DailyTask(), date, period);
	}
	
	private void setupMonthTimer() {
		monthTimer = new Timer();
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.MONTH, 1);
		
		Date date = calendar.getTime();
		monthTimer = new Timer();
		long period = 1296000000;
		monthTimer.schedule(new MonthTask(), date, period);
	}
	
	/**
	 * @ return isEmpty file
	 * */
	private boolean readFile(String path, Map map) {
		ObjectInputStream stream = null;
		try {
			stream = new ObjectInputStream(new FileInputStream(new File(new URI(path))));
			map.putAll((Map)stream.readObject());
		} catch (Exception e) {
			if (!(e instanceof EOFException))
				e.printStackTrace();
		} finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					if (!(e instanceof EOFException))
						e.printStackTrace();
				}
			}
		}
		if (map.size() == 0)
			return true;
		else 
			return false;
	}
	
	private void writeFile(String path, Map map) {
		ObjectOutputStream stream = null;
		try {
			stream = new ObjectOutputStream(new FileOutputStream(new File(new URI(path))));
			stream.writeObject(map);
			stream.flush();
		} catch (Exception e) {
			if (!(e instanceof EOFException))
				e.printStackTrace();
		} finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (Exception e) {
					if (!(e instanceof EOFException))
						e.printStackTrace();
				}
			}
		}
	}
}
